#ifndef __REACTIONDISPATCHER_H__
#define __REACTIONDISPATCHER_H__

#include "../mpl/if.h"

template<class Event>
class NoContext
{
	void NoFunction(const Event&) {};
};

template<class Reactions, class State, class EventBase, class Event, class ActionContext, class IdType>
class reactionDispatcher
{
public:
	struct WithoutAction
	{
		static ReactionResult react(State& st, const EventBase&)
		{
			return Reactions::reactWithoutAction(st);
		}
	};

	struct BaseWithAction
	{
		static ReactionResult react(State& st, const EventBase& evt)
		{
			return Reactions::reactWithAction(st, evt);
		}
	};

	struct Base
	{
		static ReactionResult react(State& st, const EventBase& evt, const IdType& )
		{
			typedef typename mpl::if_<IsSameType<ActionContext, NoContext<Event> >, WithoutAction, BaseWithAction>::type reaction;
			return reaction::react(st, evt);
		}
	};

	struct DerivedWithAction
	{
		static ReactionResult react(State& st, const EventBase& evt)
		{
			return Reactions::reactWithAction(st, *dynamic_cast<const Event*>(evt));
		}
	};

	struct Derived
	{
		static ReactionResult react(State& st, const EventBase& evt, const IdType& eventType)
		{
			if (eventType == Event::static_type())
			{
				typedef typename mpl::if_<IsSameType<ActionContext, NoContext<Event> >, WithoutAction, DerivedWithAction>::type reaction;
				return reaction::react(st, evt);
			}
			else
			{
				return ReactionResult::ReactionResult_NoReaction;
			}
		}
	};

	static ReactionResult react(State& st, const EventBase& evt, const IdType& eventType)
	{
		typedef typename mpl::if_<IsSameType<EventBase, Event>::value, Base, Derived>::type reaction;
		return reaction::react(st, evt, eventType);
	}
};


#endif
